<template>
  <div class="custom-table">
    <hot-table v-if="showTable" :settings="hotSettings" ref="hot-table">
    </hot-table>
  </div>
</template>
<script>
import eventBus from '@/utils/eventBus';
import * as XLSX from 'xlsx/xlsx.mjs';
import 'handsontable/dist/handsontable.full.css';
import { HotTable, HotColumn } from '@handsontable/vue3';
import { registerAllModules } from 'handsontable/registry';

registerAllModules();
function getColumnWidth(data) {
  const tableWidth = window.innerWidth - 50;
  const MIN_WIDTH = Math.max(tableWidth / data[0].length, 150);

  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  context.font = '18px Arial'; // 假设你使用的字体和大小

  const numRows = data.length;
  const numCols = data[0].length;

  const list = [];
  // 按列读取元素
  for (let col = 0; col < numCols; col++) {
    let maxWidth = MIN_WIDTH;
    for (let row = 0; row < numRows; row++) {
      const text = data[row][col];
      const itemWidth = context.measureText(text).width + 20; // 增加一些余量
      maxWidth = Math.max(itemWidth, maxWidth);
    }
    list.push(maxWidth);
  }
  return list;
}

// 设置Excel文件列宽
const getAutoColWidth = (data) => {
  const colWidths = data[0].map((_, colIndex) =>
    Math.max(
      ...data.map((row) => {
        // 获取这一列中每个单元格的长度
        const cellValue = row[colIndex] || '';
        return cellValue.toString().length;
      })
    )
  );
  return colWidths.map((width) => ({ wch: Math.max(10, width * 2) }));
};

const HOT_SETTINGS = {
  data: [
    ['', 'Ford', 'Volvo', 'Toyota', 'Honda'],
    ['2016', 10, 11, 12, 13],
    ['2017', 20, 11, 14, 13],
    ['2018', 30, 15, 12, 13],
  ],
  rowHeaders: true,
  colHeaders: true,
  height: 'auto',
  autoWrapRow: true,
  autoWrapCol: true,
  licenseKey: 'non-commercial-and-evaluation',
};
export default {
  name: '',
  components: {
    HotTable,
    HotColumn,
  },
  props: {
    tableDataList: { type: Array, required: true },
    allUserList: { type: Array, required: true },
    sheetName: { type: String, required: true },
    firstColumnOnlyOneUser: { type: Boolean, default: false },
    noFirstColumn: { type: Boolean, default: false },
  },
  data() {
    return {
      showTable: false,
      hotSettings: {},
    };
  },
  mounted() {
    this.getTableData();
    this.showTable = true;
    eventBus.$on('confirm', this.emitFile);
    eventBus.$on('export-excel', this.exportFile);
  },
  beforeUnmount() {
    eventBus.$off('confirm');
    eventBus.$off('export-excel');
  },
  methods: {
    getTableData() {
      const headerList = this.noFirstColumn
        ? this.tableDataList.map((e) => e.name)
        : this.tableDataList[0].sub_list.map((e) => e.sub_name);

      const bodyList = [];
      if (this.noFirstColumn) {
        const row = this.tableDataList.map((item) =>
          item.user_list.map((user) => user.user_name).join(',')
        );
        bodyList.push(row);
      } else {
        this.tableDataList.forEach(({ name, sub_list }) => {
          const row = sub_list.map(({ user_list }) =>
            (user_list || []).map((e) => e.user_name).join()
          );
          row.unshift(name);
          bodyList.push(row);
        });
      }

      const data = this.noFirstColumn
        ? bodyList
        : bodyList.map((row) => row.slice(1)); // 不包含第一列的数据
      this.hotSettings = {
        ...HOT_SETTINGS,
        data,
        colHeaders: headerList, // 使用除去行标题之外的列标题
        rowHeaders: this.noFirstColumn ? false : (index) => bodyList[index][0], // 使用数据的第一列作为行标题
        rowHeaderWidth: 200,
        colWidths: getColumnWidth(data),

        // hooks function, 表格数据变化时触发
        afterChange: (changes, source) => {
          if (source === 'loadData' || changes === null) return;

          changes.forEach(([row, col, oldValue, newValue]) => {
            this.validateCellContent(row, col, newValue);
          });
        },
      };
    },
    validateCellContent(row, col, content) {
      let isValid = true;
      let isWarning = false;
      if (content !== null && content !== '') {
        const arr = content.split(/，|,/);
        const boolean1 = arr.every((name) =>
          this.allUserList.find((e) => e.name === name)
        );
        // 第一列只能有一个人
        const boolean2 = this.firstColumnOnlyOneUser
          ? col !== 0 || arr.length <= 1
          : true;
        isValid = boolean1 && boolean2;

        isWarning = [...new Set(arr)].length !== arr.length; // 判断是否有重复项
      }

      const hotInstance = this.$refs['hot-table'].hotInstance;
      const cellMeta = hotInstance.getCellMeta(row, col);
      cellMeta.className = !isValid
        ? 'invalid-cell'
        : isWarning
        ? 'warning-cell'
        : '';
      hotInstance.render(); // Re-render to apply the new class
    },
    getExcelFile() {
      const headerList = this.noFirstColumn
        ? this.tableDataList.map((e) => e.name)
        : this.tableDataList[0].sub_list.map((e) => e.sub_name);

      // 校验内容
      const totalRows = this.tableDataList.length;
      const totalCols = headerList.length;
      if (totalRows < 1 || totalCols < 1) return;
      const hotInstance = this.$refs['hot-table'].hotInstance;
      for (let row = 0; row < totalRows; row++) {
        for (let col = 0; col < totalCols; col++) {
          const { className } = hotInstance.getCellMeta(row, col);
          if (className && className.includes('invalid-cell')) {
            console.log({ row, col });
            this.$toast('请先修改不合格的单元格');
            return;
          }
        }
      }

      // 对齐数据
      const allData = hotInstance.getData();
      let data = [headerList, ...allData];

      if (this.noFirstColumn) {
        const transformedArray = [];
        for (let i = 0; i < data[0].length; i++) {
          transformedArray.push([data[1][i], data[0][i]]);
        }
        data = transformedArray;
        data.unshift(['姓名', '职务']);
      } else {
        for (let i = 0; i < data.length; i++) {
          data[i].unshift(i === 0 ? '' : this.tableDataList[i - 1].name);
        }
      }

      const worksheet = XLSX.utils.aoa_to_sheet(data); // 将数据转换为工作表
      // 设置列宽
      worksheet['!cols'] = getAutoColWidth(data);
      const workbook = XLSX.utils.book_new(); // 创建一个新的工作簿
      XLSX.utils.book_append_sheet(workbook, worksheet, this.sheetName); // 将工作表添加到工作簿
      return workbook;
    },
    exportFile() {
      const workbook = this.getExcelFile();
      if (!workbook) return;
      XLSX.writeFile(workbook, this.sheetName + '.xlsx'); // 下载工作簿
    },

    emitFile() {
      const workbook = this.getExcelFile();
      if (!workbook) return;
      // XLSX.writeFile(workbook, 'example.xlsx'); // 下载工作簿
      // 写入到数组缓冲区
      const writeOptions = {
        bookType: 'xlsx',
        type: 'array',
      };
      const excelBuffer = XLSX.write(workbook, writeOptions);

      // 创建 Blob 对象
      const blob = new Blob([excelBuffer], {
        type: 'application/octet-stream',
      });

      this.$emit('uploadFile', blob);
    },
  },
};
</script>
<style lang="less" scoped>
.custom-table {
  width: 100%;
  height: 100%;
  :deep(.handsontable) {
    font-size: 16px;
    text-align: left;
    th {
    }
    td {
      // padding: 4px 12px;
      // min-height: 32px !important;
      padding-left: 10px;
      padding-right: 10px;
    }
    .invalid-cell {
      background-color: #f85d5d;
    }
    .warning-cell {
      background-color: #fcfc67;
    }
    /* 设置列标题的背景颜色 */
    .ht_clone_top th {
      background-color: #f7fafc;
    }

    /* 设置行标题的背景颜色 */
    .ht_clone_left th {
      background-color: rgba(0, 156, 255, 0.06);
    }
    /* 设置左上角角标头单元格的背景颜色 */
    .ht_clone_top_left_corner th {
      background-color: #f7fafc;
    }
  }
}
</style>
